package com.enterpriseDigitalPlatform.interceptor;

import com.enterpriseDigitalPlatform.anotation.AuthPer;
import com.enterpriseDigitalPlatform.anotation.NoAuth;
import com.enterpriseDigitalPlatform.dto.JsonRes;
import com.enterpriseDigitalPlatform.util.JwtUtil;
import com.enterpriseDigitalPlatform.util.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

@Slf4j
public class MyInterceptor implements HandlerInterceptor {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    @Autowired
    private RedisUtil redisUtil;

    // 拦截器 在 Controller 处理请求之前被调用
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.setAttribute("reqStartTime", System.currentTimeMillis());
        if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
            return true;
        }
        // 如果有@Noauth注解，不需要验证jwttoken
        final HandlerMethod handlerMethod = (HandlerMethod) handler;
        final Method method = handlerMethod.getMethod();
        final Class<?> clazz = method.getDeclaringClass();
        if (clazz.isAnnotationPresent(NoAuth.class) || method.isAnnotationPresent(NoAuth.class)) {
            return true;
        }
        // 获取请求头中token
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)) {
            responseResult(response, "未获取到token", 301);
            return false;
        }
        Map<String, Object> jwtdata = JwtUtil.verify(token);
        if (!((boolean) jwtdata.get("verify"))) {
            responseResult(response, "token失效", 301);
            return false;
        }
        Map<String, Object> reqUser = (Map<String, Object>) jwtdata.get("data");
        if (reqUser == null) {
            responseResult(response, "token异常", 301);
            return false;
        }
        String key = "user_" + reqUser.get("id");
        String token_redis = (String) redisUtil.get(key);
        if (!token.equals(token_redis)) {
            responseResult(response, "账号已在其他设备登录", 301);
            return false;
        }
        // 权限验证
        if (clazz.isAnnotationPresent(AuthPer.class) || method.isAnnotationPresent(AuthPer.class)) {
            int[] permissions;
            if (clazz.isAnnotationPresent(AuthPer.class)) {
                AuthPer classPermission = clazz.getAnnotation(AuthPer.class);
                permissions = classPermission.values();
            } else {
                AuthPer methodPermission = method.getAnnotation(AuthPer.class);
                permissions = methodPermission.values();
            }
            Integer role = (Integer) reqUser.get("role");
            Integer userid = (Integer) reqUser.get("id");
            boolean hasPermissions = checkPermissions(permissions, role, userid);
            if (hasPermissions) {
                responseResult(response, "无权限", 300);
                return false;
            }
        }
        request.setAttribute("jwtData", reqUser);
        return true;
    }

    // true 无权限 false 有权限
    private boolean checkPermissions(int[] permissions, Integer role, Integer userid) {
        if (userid == 1) {
            return false;
        }
        for (int permission : permissions) {
            if (permission == role) {
                return false;
            }
        }
        return true;
    }

    // 处理响应数据格式
    private void responseResult(HttpServletResponse response, String msg, int code) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.setContentType("application/json; charset=UTF-8");
            response.getWriter().write(OBJECT_MAPPER.writeValueAsString(new JsonRes(code, msg)));
            response.getWriter().close();
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

    // 在完全处理请求后被调用
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
